package controllers;

import java.beans.PropertyDescriptor;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

import models.LatoTemplate;
import models.SysField;
import models.SysTable;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.LazyDynaBean;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.fileupload.FileUploadException;

import com.google.gson.JsonArray;

import play.Logger;
import play.db.DB;
import play.db.jpa.Blob;
import play.libs.Codec;
import play.libs.Files;
import play.mvc.Controller;
import utils.DBHelper;
import utils.JsonHelper;
/**
 * This is the main interface use REST to communicate the client.
 * <p>
 * Template interface:
 * <ul>
 *  <li><code>boolean checkTableNameExist(String tableName);</code>
 *  <p>route: GET /template/exist/{tableName}
 *  <p>test URL: <a href="http://localhost:9000/template/exist/GateInOrder">http://localhost:9000/template/exist/GateInOrder</a>
 *  <p>check if TableName exist
 *
 *  <li><code>String getTemplateList(String categoryId);</code>
 *  <p>route: GET     /templates/{categoryId}
 *  <p>test URL: <a href="http://localhost:9000/templates/1">http://localhost:9000/templates/1</a>
 *  <p>get the template list json by categoryId
 *  <li><code>String getTemplate(String templateId);</code>
 *  <p>route: GET     /template/{templateId}
 *  <p>test URL: <a href="http://localhost:9000/template/1">http://localhost:9000/template/1</a>
 *  <p>get the template json
 *  <li><code>String deleteTemplate(String templateId);</code>
 *  <p>route: DELETE     /template/{templateId}
 *  <p>test URL: can not test by GET
 *  <p>delete the template, if return string length=0 means delete successfully, if return string length>0 means delete fails and string is the err msg.
 *  <li><code>String saveTemplate(String templateJson);</code>
 *  <p>route: POST    /template
 *  <p>test URL: can not test by GET
 *  <p>if templateId>0 means update template, otherwise will create template.
 *  </ul>
 *
 * <p>
 * Form interface:
 * <ul>
 *  <li><code>String getFormList(String templateId);</code>
 *  <p>get Form List by templateId, return form list in json format.
 *  <li><code>String getForm(String formId);</code>
 *  <p>get the Form by formId, return form data in json format.
 *  <li><code>String deleteForm(String formId);</code>
 *  <p>delete the form, if return string length=0 means delete successfully, if return string length>0 means delete fails and string is the err msg.
 *  <li><code>String saveForm(String formJson);</code>
 *  <p>if templateId>0 means update form, otherwise will create form.
 *  </ul>
 *
 * @author Liura
 * @since 2011-4-25
 */

public class LatoTemplateDelegate extends Controller{
	/**
	 * check if TableName exist
	 * @param tableName
	 * @return true:TableName exist, false:TableName not exist
	 */
	public static boolean checkTableNameExist(String tableName) {
		if(DBHelper.getTableMap().containsKey(tableName.toUpperCase()))
			return true;
		return false;
	}

	/**
	 * get the template list json
	 * @return  template list json
	 */
	public static String getTemplateList(String catalogId) {
		List<LatoTemplate> list = LatoTemplate.find("byCatalogId", catalogId).fetch();
		for (LatoTemplate latoTemplate : list) {
			latoTemplate.templateJson="";
		}
		Logger.info("getTemplateList size:"+list.size());
		JSONArray jsonArray = JSONArray.fromObject(list);
		return jsonArray.toString();
	}

	/**
	 * getTemplate
	 * 
	 * return template.json
	 */
	public static String getTemplate(String templateId) {
		LatoTemplate t = LatoTemplate.findById(Long.valueOf(templateId));
		Logger.info(t.templateJson);
		if(t!=null){			
			return t.templateJson;
		}
		
		return "";
	}

	/**
	 * deleteTemplate
	 */
	public static String deleteTemplate(String templateId) {
		LatoTemplate t = LatoTemplate.findById(Long.valueOf(templateId));
		if(t!=null){
			t.delete();
		}		
		return "";
	}	
	
	/**
	 * deleteTemplate
	 */
	public static String getTable(String tableName) {
		return DBHelper.getTableDefineBean(tableName).toString();	
	}	

	/**
	 * getTemplate   return sheetStyle, tableDefine
	 */
	public String getTemplate1(String templateId) {
		//template root
		DynaBean template = new LazyDynaBean();
		template.set("SheetStyleURL", "sheet_style/001");


		SysTable table = SysTable.findById(Long.valueOf(templateId));
		if (table == null)
			return "no template found.";

		DynaBean tableDefine = getSysTableJson(table);
		tableDefine.set("TemplateId", String.valueOf(table.id));
		tableDefine.set("TemplateName", table.name);

		template.set("TableDefine", tableDefine);

		JSONObject jsonObject = JSONObject.fromObject(template);
		System.out.println(jsonObject);
		return jsonObject.toString();
	}

	private DynaBean getSysTableJson(SysTable table) {
		if (table == null)
			return null;
		PropertyDescriptor[] pdArray = PropertyUtils.getPropertyDescriptors(SysField.class);
		List<SysField> fields = SysField.find("byTable", table).fetch();
		DynaBean template = new LazyDynaBean();
		template.set("tableName", table.name);

		for (int i = 0; i < fields.size(); i++) {
			SysField field = fields.get(i);
			DynaBean fieldBean = new LazyDynaBean();
			for (PropertyDescriptor propertyDescriptor : pdArray) {
				String propertyName = propertyDescriptor.getName();
				Object propertyValue;
				try {
					if ("refTable".equalsIgnoreCase(propertyName)) {
						SysTable refTable = field.refTable;
						propertyValue = getSysTableJson(refTable);
					} else
						propertyValue = BeanUtils.getProperty(field, propertyName);

					fieldBean.set(propertyName, propertyValue);
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					e.printStackTrace();
				} catch (NoSuchMethodException e) {
					e.printStackTrace();
				}
			}
			template.set("fieldList", i, fieldBean);
		}
		return template;
	}

	public String getType(String type) {
		if (type.trim().equals("String")) {
			return "VARCHAR(200)";
		}
		if (type.trim().equals("Date")) {
			return "Date";
		}
		return "";
	}

	public static String saveTemplate(String json, File file, String catalogId) throws Exception {
		System.out.println("json:" + json + ", file:" + file+ ", catalogId:" + catalogId);

		DynaBean rootBean = JsonHelper.getDynaBeanFromJson(json);
		
		LatoTemplate tem = new LatoTemplate();
		boolean isCreate = true;
		if(rootBean.get("templateId").toString().length()>0){
			tem.id = Long.parseLong(rootBean.get("templateId").toString()) ;		
			isCreate = false;
			tem = LatoTemplate.findById(tem.id);
			if(tem==null)
				throw new Exception("no template found.");
		}
		if(file !=null && !isCreate &&tem.filePath.length()>0){
			String toName = Blob.getStore().getPath()+File.separator+tem.filePath;			
			boolean isDelete = new File(toName).delete();
		}
		if(file !=null){
			String toName = Codec.UUID()+".ejun";
			LatoTemplateDelegate.saveUploadFile(file, toName);
			tem.filePath = toName;
		}
		
		tem.templateName = (String) rootBean.get("templateName");		
		tem.templateJson = json;
		tem.catalogId = catalogId;
		tem.save();
		Long templateId = tem.getId();

		DBHelper.printDBstructure();
		
//		JsonHelper.printDynaProperty(rootBean);
		List bean = (List)rootBean.get("tableMapList");
		for (Object object : bean) {
			DynaBean tableBean = (DynaBean)object;
			JsonHelper.printDynaProperty(tableBean);
			DBHelper.alterTable(tableBean);

		}
		DBHelper.printDBstructure();
		if(isCreate){
			String str = "templateId\":\""+templateId+"\"";
			json = json.replaceFirst("templateId\":\"\"", str);
		}
		tem.templateJson=json;
		tem.save();
		return json;//JsonHelper.getJsonFromBean(rootBean).toString();
	}


	public static File getTemplateFile(Long templateId) throws Exception {
		LatoTemplate t = LatoTemplate.findById(templateId);
		File store = Blob.getStore();
		File to = new File(store.getPath()+File.separator+t.filePath);
		return to;
	}


	static void saveUploadFile(File fileFrom, String toFileName)
			throws FileUploadException, Exception {
		File store = Blob.getStore();		
		String toName = store.getPath()+File.separator+toFileName;
		Logger.info(toName);
		File to = new File(toName);
		Files.copy(fileFrom, to);
	}

}
